package org.ngmj.protocol;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;

public interface Serialize {
    <T> byte[] serialize(T obj);

    <T> T deserialize(byte[] bytes, Class<T> clazz);

    @Slf4j
    enum SerializerAlgorithm implements Serialize {
        Java {
            @Override
            public <T> byte[] serialize(T obj) {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                try {
                    ObjectOutputStream oos = new ObjectOutputStream(bos);
                    oos.writeObject(obj);
                    return bos.toByteArray();
                } catch (IOException e) {
                    throw new RuntimeException("序列化失败", e);
                } finally {
                    try {
                        bos.close();
                    } catch (IOException e) {
                        log.error("close error", e);
                    }
                }
            }

            @Override
            public <T> T deserialize(byte[] bytes, Class<T> clazz) {
                ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
                try {
                    ObjectInputStream ois = new ObjectInputStream(bis);
                    return (T) ois.readObject();
                } catch (IOException | ClassNotFoundException e) {
                    throw new RuntimeException("反序列化失败", e);
                } finally {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        log.error("close error", e);
                    }
                }
            }
        },
        Json {
            ObjectMapper om = new ObjectMapper();

            @Override
            public <T> byte[] serialize(T obj) {
                try {
                    String json = om.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
                    return json.getBytes(StandardCharsets.UTF_8);
                } catch (Exception e) {
                    log.error("序列化失败", e);
                    throw new RuntimeException(e);
                }
            }

            @Override
            public <T> T deserialize(byte[] bytes, Class<T> clazz) {
                String json = new String(bytes, StandardCharsets.UTF_8);
                try {
                    return om.readValue(json, clazz);
                } catch (JsonProcessingException e) {
                    log.error("反序列化失败", e);
                    throw new RuntimeException(e);
                }
            }
        }
    }

    // 需要从协议的字节中得到是哪种序列化算法
    static SerializerAlgorithm getByInt(int type) {
        SerializerAlgorithm[] array = SerializerAlgorithm.values();
        if (type < 0 || type > array.length - 1) {
            throw new IllegalArgumentException("超过 SerializerAlgorithm 范围");
        }
        return array[type];
    }

}
